package cn.my.learning.web;

import cn.my.learning.security.BeforeLoginRequest;
import cn.my.learning.domain.LibraryList;
import cn.my.learning.domain.User;
import cn.my.learning.domain.Verification;
import cn.my.learning.repository.UserRepository;
import cn.my.learning.service.UserServiceImpl;
import cn.my.learning.service.VerificationServiceImpl;
import cn.my.learning.util.EmailUtil;
import cn.my.learning.util.FileUtil;
import cn.my.learning.util.IsLoginUtil;
import com.mongodb.WriteResult;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * Created by Administrator on 2017/3/26.
 * 用户访问管理类
 */
@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private VerificationServiceImpl verificationService;

    //初始化用户文件夹(本地路径)
    @Value("${user.head-faviconImg.path}")
    private String localUploadPath;

    //初始化用户文件夹(项目路径)
    @Value("${user.head-faviconImg.projectPath}")
    private String projectUploadPath;

    //测试时使用
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @ApiOperation(value = "跳转到用户登录界面", httpMethod = "GET", notes = "跳转到用户登录界面")
    @RequestMapping(value = "/userLogin")
    public String goUserLogin(HttpServletRequest httpServletRequest) {
        //记录跳转前的页面
        String beforeLoginRequestUrl = httpServletRequest.getHeader("Referer");
        BeforeLoginRequest.setRequestUrl(beforeLoginRequestUrl);
        return "loginPage";
    }

    @ApiOperation(value = "跳转到用户信息页面", httpMethod = "GET", notes = "跳转到用户信息页面")
    @RequestMapping(value = "/userInfo")
    public String listLibrary(HttpServletRequest httpServletRequest) {
        String userName = new IsLoginUtil().IsLogin(httpServletRequest);
        if (!Objects.equals(userName, "未登录用户")){
            User user = userRepository.findUsernameByAccount(httpServletRequest.getRemoteUser());
            httpServletRequest.setAttribute("Username", user.getUsername());
            return "userInformation";
        }
        return "redirect:/my_home";
    }

    @ApiOperation(value = "跳转到忘记密码页面", httpMethod = "GET", notes = "跳转到修改密码页面")
    @RequestMapping(value = "/forgetPassword")
    public String goForgetPassword(HttpServletRequest httpServletRequest) {
        String userName = new IsLoginUtil().IsLogin(httpServletRequest);
        if (!Objects.equals(userName, "未登录用户")){
            return "forgetPassword";
        }
        return "redirect:/my_home";
    }

    @ApiOperation(value = "跳转到修改密码页面", httpMethod = "GET", notes = "跳转到修改密码页面")
    @RequestMapping(value = "/changePassword")
    public String goChangePassword(HttpServletRequest httpServletRequest) {
        String userName = new IsLoginUtil().IsLogin(httpServletRequest);
        if (!Objects.equals(userName, "未登录用户")){
            User user = userRepository.findUsernameByAccount(httpServletRequest.getRemoteUser());
            httpServletRequest.setAttribute("Username", user.getUsername());
            return "changePassword";
        }
        return "redirect:/my_home";
    }

    @ApiOperation(value = "获取用户信息", httpMethod = "GET", notes = "获取用户信息")
    @RequestMapping(value = "get_userInfo")
    @ResponseBody
    public List<User> getUser(@RequestParam String account) {
        return userService.findByAccount(account);
    }

    @ApiOperation(value = "判断用户账号是否存在", httpMethod = "GET", notes = "获取用户信息")
    @RequestMapping(value = "get_allAccount")
    @ResponseBody
    public boolean getAllAccount(@RequestParam String account) {
        List<User> users = userService.findByAccount(account);
        return users == null || users.size() == 0;
    }

    @ApiOperation(value = "获取用户文章目录信息", httpMethod = "GET", notes = "获取用户文章目录信息")
    @RequestMapping(value = "get_userArticle")
    @ResponseBody
    public Page<LibraryList> getUserArticle(@RequestParam String account,@RequestParam Integer currentPage) {
        return userService.findUserArticle(account,currentPage);
    }

    @ApiOperation(value = "获取用户收藏目录信息", httpMethod = "GET", notes = "获取用户收藏目录信息")
    @RequestMapping(value = "get_articleCollection")
    @ResponseBody
    public List<LibraryList> getArticleCollection(@RequestParam List<String> articleCollection) {
        return userService.findarticleCollection(articleCollection);
    }

    @ApiOperation(value = "注册用户", httpMethod = "POST", notes = "注册用户", response = boolean.class)
    @RequestMapping(value = "addAccount")
    @ResponseBody
    public boolean addAccount(@ApiParam(required = true, name = "user", value = "获取添加user对象") @RequestBody User user, HttpServletRequest httpServletRequest) {

        //判断用户是否注册成功
        user.setLoginNow(false);
        user.setRecentLoginTime("");
        user.setSessionId("");
        user.setRecentLoginAddress(httpServletRequest.getRemoteAddr());
        boolean addUser = userService.addUser(user);

        //注册成功后创建用户文件夹
        if (addUser){

            //创建文件夹
            File defaultImgPath = new File(projectUploadPath + "userInfo.png");
            File userFile = new File(localUploadPath + user.getAccount() + "\\");
            File cacheFile = new File(projectUploadPath + user.getAccount() + "\\");

            //判断文件夹是否存在（理论上不存在）
            if (!userFile.exists() && !cacheFile.exists())
            {
                //创建文件夹
                boolean createUserFile = userFile.mkdirs();
                boolean createCacheFile = cacheFile.mkdirs();
                if (createUserFile && createCacheFile){
                    System.out.println("用户文件夹及用户缓存文件夹创建成功");
                }
                else {
                    String errInfo = "用户文件夹及用户缓存文件夹创建失败";
                    if (!createUserFile){
                        errInfo = "用户文件夹创建失败";
                        System.out.println(errInfo);
                    }
                    else if (!createCacheFile){
                        errInfo = "用户缓存文件夹创建失败";
                        System.out.println(errInfo);
                    }
                    System.out.println(errInfo);
                }

                try {
                    //设置用户默认头像
                    boolean IsSetUpDefaultImg = new FileUtil().copyFile(defaultImgPath.toString(),userFile.toString());
                    boolean IsSetupDefaultImgInCache = new FileUtil().copyFile(defaultImgPath.toString(), cacheFile.toString());

                    //设置成功返回true
                    if (IsSetUpDefaultImg && IsSetupDefaultImgInCache){ return true; }

                } catch (IOException e) { e.printStackTrace(); }
                return false;
            }
            return true;
        }
        else {
            return false;
        }
    }

    @ApiOperation(value = "修改用户信息", httpMethod = "POST", notes = "修改用户", response = boolean.class)
    @RequestMapping(value = "update_userInfo")
    @ResponseBody
    public boolean updateUserInfo(@ApiParam(required = true, name = "user", value = "获取修改user对象") @RequestBody User user, HttpServletRequest httpServletRequest) {
        //查询出where传过来的文章在数据库是否有这个对象
        Query query = Query.query(Criteria.where("account").is(user.getAccount()));

        //编写Update操作
        Update update = Update.update("username", user.getUsername())
                .set("signature",user.getSignature())
                .set("sex", user.getSex())
                .set("email", user.getEmail())
                .set("phone", user.getPhone())
                .set("homePath", user.getHomePath());

        //执行查询语句并update
        WriteResult writeResult = mongoTemplate.updateFirst(query, update, User.class);

        //返回修改状态（是否成功修改）
        return writeResult.isUpdateOfExisting();
    }

    @ApiOperation(value = "验证原密码", notes = "验证原密码", response = boolean.class)
    @RequestMapping(value = "/verify_old_password")
    @ResponseBody
    public Boolean verifyOldPassword(HttpServletRequest httpServletRequest,@RequestParam String oldPassword) {
        String account = new IsLoginUtil().IsLogin(httpServletRequest);
        List<User> list=userService.findByAccountAndPassword(account,oldPassword);
        return list == null || list.size() == 0;
    }

    @ApiOperation(value = "修改密码", httpMethod = "POST", notes = "修改密码", response = boolean.class)
    @RequestMapping(value = "update_password")
    @ResponseBody
    public boolean updatePassword(HttpServletRequest httpServletRequest, @RequestParam String password) {

        String account = httpServletRequest.getRemoteUser();
        //返回修改状态（是否成功修改）
        return userService.updatePassword(account,password);
    }

    @ApiOperation(value = "发送验证邮件", httpMethod = "POST", notes = "发送验证邮件", response = boolean.class)
    @RequestMapping(value = "send_email")
    @ResponseBody
    public boolean sendEmail(@RequestParam String account) throws ParseException, MessagingException {

        //返回List判断用户邮箱是否匹配
        List<User> user_info = userService.findUserEmailAddressByUserAccount(account);
        if (user_info.size() != 0 ){
            //获取匹配成功后返回的用户信息对象
            User user = user_info.get(0);
            if (user.getEmail() != null){
                //验证码
                String VerifyRandomString = new EmailUtil().coreEmailController("找回密码", null, null, user.getEmail(), user.getUsername());
                return verificationService.addVerification(account, user.getEmail(), VerifyRandomString);
            }
            return false;
        }
        return false;
    }

    @ApiOperation(value = "验证密码", httpMethod = "POST", notes = "验证密码", response = boolean.class)
    @RequestMapping(value = "verify_password")
    @ResponseBody
    public boolean verifyVerification(@RequestParam String account, @RequestParam String newPassword, @RequestParam String randomString) throws ParseException {

        String emailAddress = userService.findUserEmailAddressByUserAccount(account).get(0).getEmail();
        if (emailAddress != null){
            //获取验证码对象
            List<Verification> verification = verificationService.findByEmailAddressAndAccount(emailAddress, account);
            if (verification.size() == 0) return false;

        /* 验证码未失效
         * Objects.equals(randomString, verificationString) 判断返回的验证码和用户填写到验证码是否一致
         * userService.modifyUserPassword(account, newPassword) 修改密码
         * verificationService.ChangeVerificationExpired(verificationString) 修改验证码使用记录
         * &&只要有一个为false全为false，且按顺序从左到右验证
         *
         * 获取验证码，失效时间和开始时间
         */
            String verificationString = verification.get(0).getVerification();
            String verificationDeadline = verification.get(0).getEnd_time();
            String verificationStartTime = verification.get(0).getStart_time();
            boolean IsExpired = new EmailUtil().detla_T(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())), verificationDeadline, verificationStartTime);
            return IsExpired && Objects.equals(randomString, verificationString) && userService.modifyUserPassword(account, newPassword) && verificationService.ChangeVerificationExpired(verificationString);
        }
        return false;
    }

    @ApiOperation(value = "添加用户文章关注")
    public boolean addUserFocusOnArticleCollection(@RequestParam String userAccount, @RequestParam String libraryCode){
        return true;
    }

}
